import axios from 'axios'
import qs from 'qs'
import md5 from 'blueimp-md5'
import VueStore from '@/store'
// import { EpMessage as Message } from 'ep-ui'
import Settings from '@/settings'
import { deepMerge, deleteEmptyProperty } from '@/utils/data'
import { dateFormat } from '@/utils/date'
import cookie from '@/utils/cookie'
import localStorage from '@/utils/localStorage'
import { CODE_401, CODE_200 } from '@/common/vars'
import router from '@/router'
let Message = require('ep-ui').EpMessage

Message = Message ? Message : global.EpMessage
let settings = global.settings ? global.settings : Settings
if (localStorage.getLocalStorage('lastTokenType') == 'H4a') {
  settings.headerAuthKey = 'token'
  settings.hunterUserOrigin = 'H4A'
}
else{
  settings.headerAuthKey = 'hunterToken'
  settings.hunterUserOrigin = 'hunterToken'
}
// 沿用原先 ep-front 的那套命名
const DATA_TYPE = {
  form: {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    }
    // factoryBody(data) { return qs.stringify(data) }
  },
  blob: {
    headers: {
      'Content-Type': 'application/octet-stream'
    }
    // factoryBody: data => data
  },
  file: {
    headers: {}
    // factoryBody(data) {
    //   let formData = new FormData()
    //   if (null !== data && typeof data === 'object') {
    //     for (let item in data) {
    //       formData.append(item, data[item])
    //     }
    //   }
    //   return formData
    // }
  },
  json: {
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    }
    // factoryBody: data => data
  },
  html: {
    headers: {
      'Content-Type': 'text/html'
    }
    // factoryBody: data => data
  },
  xml: {
    headers: {
      'Content-Type': 'application/xml, text/xml'
    }
    // factoryBody: data => data
  }
}

const dataTypeDefault = DATA_TYPE[settings.reqDataTypeDefault || 'json']

const service = axios.create({
  baseURL: global.HOST,
  timeout: settings.reqTimeout, // 老 chunk
  headers: deepMerge(
    {},
    {
      // other
    },
    dataTypeDefault.headers
  )
})

/**
 * 请求拦截器
 */
service.interceptors.request.use(
  config => {
    // [可选]通过自定义属性 dataType 方便定义 content-type
    if (config.dataType) {
      let reqSetting = DATA_TYPE[config.dataType]
      if (reqSetting) {
        config.headers = deepMerge({}, config.headers, reqSetting.headers)
      }
    }
    if ((settings.headerSign && config.headerSign !== false) || (!settings.headerSign && config.headerSign === true)) {
      config.headers[settings.headerSignName] = calaulatorSign(config)
    }

    if (config.dataType === 'form') {
      config.data = qs.stringify(config.data)
    }

    if (settings.debugUser) {
      config.headers['debug-user'] = config.headers['debug-user'] || settings.debugUser
    }
    if (global.appCode) {
      config.headers['Origin-App-Code'] = config.headers['Origin-App-Code'] || global.appCode
    }
    if (settings.hunterUserOrigin) {
      config.headers['Hunter-User-Origin'] = config.headers['Hunter-User-Origin'] || settings.hunterUserOrigin
    }
    // 新架子现在tokenName 是localstorage或者cookie中token的 key;:
    //  headerAuthKey 是请求头中 token 的key，原先新架子好像都是都用了 tokenName，
    // 后来为了区分开来就弄成两个了,这里坐下兼容
    if (VueStore.state.app.authorization) {
      config.headers[settings.headerAuthKey || settings.tokenName] =
        config.headers[settings.headerAuthKey || settings.tokenName] || VueStore.state.app.authorization
    }
    if (VueStore.state.user && VueStore.state.user.token) {
      config.headers[settings.headerAuthKey || settings.tokenName] =
        config.headers[settings.headerAuthKey || settings.tokenName] || VueStore.state.user.token
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

/**
 * 返回拦截器
 * 默认接收的是 {code：xxx, data: xxx}
 * 可根据实际情况自行更改
 */
service.interceptors.response.use(
  response => {
    let { config } = response
    // 接口200
    if (response.status === 200) {
      // 通过自定义属 pureResponse将返回内容原样返回
      if (config.pureResponse) {
        return Promise.resolve(response)
      }
      // code = 200 or flag = 'T'
      if (CODE_200.indexOf(response.data.code) !== -1 || CODE_200.indexOf(response.data.flag) !== -1) {
        return Promise.resolve(response)
      }
      if (CODE_401.indexOf(response.data.code) !== -1 || CODE_401.indexOf(response.data.errorCode) !== -1) {
        // token过期
        VueStore.dispatch('logout')
        if (!settings.tokenExpireMessage) {
          // 兼容老框架 - start
          localStorage.delLocalStorage(settings.tokenName)
          cookie.delCookie(settings.tokenName)
          // 兼容老框架 - end
          window.location.reload()
        }
        return Promise.reject(response)
      } else if (CODE_200.indexOf(response.data.code) === -1 && CODE_200.indexOf(response.data.flag) === -1) {
        // 非 code 200
        return Promise.reject(response)
      }
    } else {
      return Promise.reject(response)
    }
  },
  error => {
    return Promise.reject(error)
  }
)

export function request(reqConfig) {
  return new Promise((resolve, reject) => {
    console.log(reqConfig)
    service(reqConfig)
      .then(res => {
        console.log(res)
        if (reqConfig.showSuccess !== false && reqConfig.showSuccess !== undefined) {
          Message({
            type: 'success',
            message: reqConfig.showSuccess === true ? '请求成功' : reqConfig.showSuccess
          })
        }
        resolve(res)
      })
      .catch(err => {
        if (reqConfig.showError !== false) {
          try {
            if (
              settings.tokenExpireMessage &&
              (CODE_401.indexOf(err.data && err.data.code) !== -1 || CODE_401.indexOf(err.data && err.data.errorCode) !== -1)
            ) {
              Message({
                type: 'info',
                message: err.data.bizMessage || err.data.message || `登录信息过期，请重新登录`
              })
              // /(?<=#\/)\w*(?=\?)/
              // 重新回到登录页 这里为了不引入 router 所以这么操作
              window.location.replace(location.origin + location.pathname + '#/login')
              // if (window.history) {
              //   window.history.pushState(null, '', location.origin + location.pathname + '#/login')
              //   window.history.pushState(null, '', location.origin + location.pathname + '#/login')
              //   window.history.go(-1)
              // } else {
              //   setTimeout((_) => {
              //     location.href = location.origin + location.pathname
              //   }, 0)
              // }
              // reject('登录信息过期，请重新登录')
              return reject(err)
            }
            Message({
              type: 'danger',
              // code: ${err.data.code || err.data.errorCode}
              message: `${err.data.bizMessage || err.data.message || err.data.errorInfo}`
            })
          } catch (error) {
            console.log(error, err)
            Message({
              type: 'danger',
              message: `未知错误`
            })
          }
        }
        reject(err)
      })
  })
}

export function post(config) {
  config.method = 'post'
  return request(config)
    .then(res => {
      return res.data
    })
    .catch(err => {
      if ((err.errCode || err.data.errCode) === '401') {
        router.push('login')
      }
      return Promise.reject(err)
    })
}

export function get(config) {
  config.method = 'get'
  return request(config)
    .then(res => {
      return res.data
    })
    .catch(err => {
      if ((err.errCode || err.data.errCode) === '401') {
        router.push('login')
      }
      return Promise.reject(err)
    })
}

export function put(config) {
  config.method = 'put'
  return request(config)
    .then(res => {
      return res.data
    })
    .catch(err => {
      if ((err.errCode || err.data.errCode) === '401') {
        router.push('login')
      }
      return Promise.reject(err)
    })
}

export function del(config) {
  config.method = 'delete'
  return request(config)
    .then(res => {
      return res.data
    })
    .catch(err => {
      if ((err.errCode || err.data.errCode) === '401') {
        router.push('login')
      }
      return Promise.reject(err)
    })
}

/**
 * 将 header 里的改成小写方便取和判断
 * eg Content-Type: "application/json; charset=utf-8" - >content-type: "application/json; charset=utf-8"
 */
function geLowerCaseInHeaders(key, headers) {
  let obj = {}
  for (let key in headers) {
    obj[key.toLocaleLowerCase()] = headers[key]
  }
  return obj[key]
}

// 加签方法
export function calaulatorSign(config) {
  let { method, params, data, headers } = config
  let contentType = geLowerCaseInHeaders('content-type', headers)
  // 验签的多种形式
  let signChangeData = '{}'
  if (method === 'get') {
    signChangeData = qs.stringify(params) || '{}'
  } else {
    // json删除空白节点 [按需]
    if (contentType.indexOf('application/json') > -1) {
      // 删除空节点
      deleteEmptyProperty(data, [undefined, null])
      signChangeData = data ? JSON.stringify(data) : '{}'
    }
    // form表单提交，拼装order，后端获取拼接验证
    if (data && contentType.indexOf('application/x-www-form-urlencode') > -1) {
      signChangeData = data ? JSON.stringify(data) : '{}'
      // 规定，去除双引号
      signChangeData = signChangeData.replaceAll('"', '')
      let orders = []
      for (let key in data) {
        if (Object.hasOwnProperty.call(data, key)) {
          orders.push(key)
        }
      }
      data.epFrameworkOrder = orders.join(',')
    }
  }
  let today = dateFormat(new Date(), 'YYYY-MM-DD')

  return md5(EPENV.md5Prefix + signChangeData + today)
}
